home *** CD-ROM | disk | FTP | other *** search
/ Programming Windows 95 with MFC / Programming Windows 95 with MFC (Microsoft Programming Series)(097-0001465)(1996).iso / CODE / Chap06 / Paint3 / Paint3.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-05  |  10.2 KB  |  404 lines

  1. //***********************************************************************
  2. //
  3. //  Paint3.cpp
  4. //
  5. //***********************************************************************
  6.  
  7. #define OEMRESOURCE
  8.  
  9. #include <afxwin.h>
  10. #include <afxdlgs.h>
  11. #include "Resource.h"
  12. #include "Paint3.h"
  13.  
  14. CMyApp myApp;
  15.  
  16. /////////////////////////////////////////////////////////////////////////
  17. // CMyApp member functions
  18.  
  19. BOOL CMyApp::InitInstance ()
  20. {
  21.     m_pMainWnd = new CMainWindow;
  22.     m_pMainWnd->ShowWindow (m_nCmdShow);
  23.     m_pMainWnd->UpdateWindow ();
  24.     return TRUE;
  25. }
  26.  
  27. /////////////////////////////////////////////////////////////////////////
  28. // CMainWindow message map and member functions
  29.  
  30. BEGIN_MESSAGE_MAP (CMainWindow, CFrameWnd)
  31.     ON_WM_PAINT ()
  32.     ON_COMMAND (IDM_FILE_NEW, OnFileNew)
  33.     ON_COMMAND (IDM_FILE_OPEN, OnFileOpen)
  34.     ON_COMMAND (IDM_FILE_SAVE, OnFileSave)
  35.     ON_COMMAND (IDM_FILE_SAVE_AS, OnFileSaveAs)
  36.     ON_COMMAND (IDM_FILE_EXIT, OnFileExit)
  37.     ON_COMMAND_RANGE (IDM_WIDTH_VTHIN, IDM_WIDTH_VTHICK, OnWidth)
  38.     ON_COMMAND_RANGE (IDM_COLOR_BLACK, IDM_COLOR_WHITE, OnColor)
  39.     ON_UPDATE_COMMAND_UI (IDM_FILE_NEW, OnUpdateFileUI)
  40.     ON_UPDATE_COMMAND_UI (IDM_FILE_SAVE, OnUpdateFileUI)
  41.     ON_UPDATE_COMMAND_UI (IDM_FILE_SAVE_AS, OnUpdateFileUI)
  42.     ON_UPDATE_COMMAND_UI_RANGE (IDM_WIDTH_VTHIN, IDM_WIDTH_VTHICK,
  43.         OnUpdateWidthUI)
  44.     ON_UPDATE_COMMAND_UI_RANGE (IDM_COLOR_BLACK, IDM_COLOR_WHITE,
  45.         OnUpdateColorUI)
  46.     ON_WM_LBUTTONDOWN ()
  47.     ON_WM_MOUSEMOVE ()
  48.     ON_WM_LBUTTONUP ()
  49.     ON_WM_CONTEXTMENU ()
  50.     ON_WM_MEASUREITEM ()
  51.     ON_WM_DRAWITEM ()
  52. END_MESSAGE_MAP ()
  53.  
  54. const COLORREF CMainWindow::crColors[8] = {
  55.     RGB (  0,   0,   0),    // Black
  56.     RGB (  0,   0, 255),    // Blue
  57.     RGB (  0, 255,   0),    // Green
  58.     RGB (  0, 255, 255),    // Cyan
  59.     RGB (255,   0,   0),    // Red
  60.     RGB (255,   0, 255),    // Magenta
  61.     RGB (255, 255,   0),    // Yellow
  62.     RGB (255, 255, 255)     // White
  63. };
  64.  
  65. const char CMainWindow::szFilters[] =
  66.     "Paint Files (*.pnt)|*.pnt|All Files (*.*)|*.*||";
  67.  
  68. CMainWindow::CMainWindow ()
  69. {
  70.     m_nColor = IDM_COLOR_RED;
  71.     m_nWidth = IDM_WIDTH_MEDIUM;
  72.     m_lineArray.SetSize (0, 64);
  73.  
  74.     CString strWndClass = AfxRegisterWndClass (
  75.         0,
  76.         myApp.LoadStandardCursor (IDC_CROSS),
  77.         (HBRUSH) (COLOR_WINDOW + 1),
  78.         myApp.LoadIcon (IDR_MAINFRAME)
  79.     );
  80.     
  81.     Create (strWndClass, "Paint3", WS_OVERLAPPEDWINDOW,
  82.         rectDefault, NULL, MAKEINTRESOURCE (IDR_MAINFRAME));
  83.  
  84.     LoadAccelTable (MAKEINTRESOURCE (IDR_MAINFRAME));
  85.  
  86.     CMenu* pMenu = GetMenu ();
  87.     for (int i=0; i<8; i++)
  88.         pMenu->ModifyMenu (IDM_COLOR_BLACK + i, MF_BYCOMMAND |
  89.             MF_OWNERDRAW, IDM_COLOR_BLACK + i);
  90. }
  91.  
  92. CMainWindow::~CMainWindow ()
  93. {
  94.     DeleteAllLines ();
  95. }
  96.  
  97. void CMainWindow::OnPaint ()
  98. {
  99.     CPaintDC dc (this);
  100.     int nCount = m_lineArray.GetSize ();
  101.  
  102.     if (nCount) {
  103.         for (int i=0; i<nCount; i++)
  104.             ((CLine*) m_lineArray[i])->Draw (&dc);
  105.     }
  106. }
  107.  
  108. void CMainWindow::OnFileNew ()
  109. {
  110.     m_strFileName.Empty ();
  111.     m_strPathName.Empty ();
  112.     UpdateWindowTitle ();
  113.  
  114.     DeleteAllLines ();
  115.     Invalidate ();
  116. }
  117.  
  118. void CMainWindow::OnFileOpen ()
  119. {
  120.     CFileDialog dlg (TRUE, "pnt", "*.pnt",
  121.         OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, szFilters, this);
  122.  
  123.     if (dlg.DoModal () == IDOK) {
  124.         if (LoadFile (dlg.GetPathName ())) {
  125.             m_strFileName = dlg.GetFileTitle ();
  126.             m_strPathName = dlg.GetPathName ();
  127.             UpdateWindowTitle ();
  128.         }
  129.     }
  130. }
  131.  
  132. void CMainWindow::OnFileSave ()
  133. {
  134.     if (!m_strFileName.IsEmpty ())
  135.         SaveFile (m_strPathName);
  136.     else // Need a file name first
  137.         OnFileSaveAs ();
  138. }
  139.  
  140. void CMainWindow::OnFileSaveAs ()
  141. {
  142.     CFileDialog dlg (FALSE, "pnt", m_strPathName,
  143.         OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY,
  144.         szFilters, this);
  145.  
  146.     if (dlg.DoModal () == IDOK) {
  147.         if (SaveFile (dlg.GetPathName ())) {
  148.             m_strFileName = dlg.GetFileTitle ();
  149.             m_strPathName = dlg.GetPathName ();
  150.             UpdateWindowTitle ();
  151.         }
  152.     }
  153. }
  154.  
  155. void CMainWindow::OnUpdateFileUI (CCmdUI* pCmdUI)
  156. {
  157.     pCmdUI->Enable (m_lineArray.GetSize ());
  158. }
  159.  
  160. void CMainWindow::OnFileExit ()
  161. {
  162.     SendMessage (WM_CLOSE, 0, 0);
  163. }
  164.  
  165. void CMainWindow::OnWidth (UINT nID)
  166. {
  167.     m_nWidth = nID;
  168. }
  169.  
  170. void CMainWindow::OnColor (UINT nID)
  171. {
  172.     m_nColor = nID;
  173. }
  174.  
  175. void CMainWindow::OnUpdateWidthUI (CCmdUI* pCmdUI)
  176. {
  177.     pCmdUI->SetCheck (pCmdUI->m_nID == m_nWidth);
  178. }
  179.  
  180. void CMainWindow::OnUpdateColorUI (CCmdUI* pCmdUI)
  181. {
  182.     pCmdUI->SetCheck (pCmdUI->m_nID == m_nColor);
  183. }
  184.  
  185. void CMainWindow::OnLButtonDown (UINT nFlags, CPoint point)
  186. {
  187.     m_ptFrom = point;
  188.     m_ptTo = point;
  189.     SetCapture ();
  190. }
  191.  
  192. void CMainWindow::OnMouseMove (UINT nFlags, CPoint point)
  193. {
  194.     if (GetCapture () == this) {
  195.         CClientDC dc (this);
  196.         InvertLine (&dc, m_ptFrom, m_ptTo);
  197.         InvertLine (&dc, m_ptFrom, point);
  198.         m_ptTo = point;
  199.     }
  200. }
  201.  
  202. void CMainWindow::OnLButtonUp (UINT nFlags, CPoint point)
  203. {
  204.     static UINT nWidths[5] = { 1, 8, 16, 24, 32 };
  205.  
  206.     if (GetCapture () == this) {
  207.         ReleaseCapture ();
  208.  
  209.         CClientDC dc (this);
  210.         InvertLine (&dc, m_ptFrom, m_ptTo);
  211.         CLine* pLine = NULL;
  212.  
  213.         try {
  214.             pLine = new CLine (m_ptFrom, m_ptTo,
  215.                 nWidths[m_nWidth - IDM_WIDTH_VTHIN],
  216.                 crColors[m_nColor - IDM_COLOR_BLACK]);
  217.  
  218.             m_lineArray.Add (pLine);
  219.             pLine->Draw (&dc);
  220.         }
  221.         catch (CMemoryException* e) {
  222.             MessageBox ("Out of memory. You must clear the " \
  223.                 "drawing area before adding more lines.", "Error",
  224.                 MB_ICONEXCLAMATION | MB_OK);
  225.  
  226.             if (pLine != NULL)
  227.                 delete pLine;
  228.             e->Delete ();   
  229.         }       
  230.     }
  231. }
  232.  
  233. void CMainWindow::OnContextMenu (CWnd* pWnd, CPoint point)
  234. {
  235.     CRect rect;
  236.     GetClientRect (&rect);
  237.     ClientToScreen (&rect);
  238.  
  239.     if (rect.PtInRect (point)) {
  240.         CMenu menu;
  241.         menu.LoadMenu (IDR_CONTEXTMENU);
  242.         CMenu* pContextMenu = menu.GetSubMenu (0);
  243.  
  244.         for (int i=0; i<8; i++)
  245.             pContextMenu->ModifyMenu (IDM_COLOR_BLACK + i,
  246.                 MF_BYCOMMAND | MF_OWNERDRAW, IDM_COLOR_BLACK + i);
  247.  
  248.         pContextMenu->TrackPopupMenu (TPM_LEFTALIGN | TPM_LEFTBUTTON |
  249.             TPM_RIGHTBUTTON, point.x, point.y, this);
  250.         return;
  251.     }
  252.     CFrameWnd::OnContextMenu (pWnd, point);
  253. }
  254.  
  255. void CMainWindow::OnMeasureItem (int nIDCtl, LPMEASUREITEMSTRUCT lpmis)
  256. {
  257.     lpmis->itemWidth = ::GetSystemMetrics (SM_CYMENU) * 4;
  258.     lpmis->itemHeight = ::GetSystemMetrics (SM_CYMENU);
  259. }
  260.  
  261. void CMainWindow::OnDrawItem (int nIDCtl, LPDRAWITEMSTRUCT lpdis)
  262. {
  263.     BITMAP bm;
  264.     CBitmap bitmap;
  265.     bitmap.LoadOEMBitmap (OBM_CHECK);
  266.     bitmap.GetObject (sizeof (bm), &bm);
  267.  
  268.     CDC dc;
  269.     dc.Attach (lpdis->hDC);
  270.  
  271.     CBrush* pBrush = new CBrush (::GetSysColor ((lpdis->itemState &
  272.         ODS_SELECTED) ? COLOR_HIGHLIGHT : COLOR_MENU));
  273.     dc.FrameRect (&(lpdis->rcItem), pBrush);
  274.     delete pBrush;
  275.  
  276.     if (lpdis->itemState & ODS_CHECKED) {
  277.         CDC dcMem;
  278.         dcMem.CreateCompatibleDC (&dc);
  279.         CBitmap* pOldBitmap = dcMem.SelectObject (&bitmap);
  280.  
  281.         dc.BitBlt (lpdis->rcItem.left + 4, lpdis->rcItem.top +
  282.             (((lpdis->rcItem.bottom - lpdis->rcItem.top) -
  283.             bm.bmHeight) / 2), bm.bmWidth, bm.bmHeight, &dcMem,
  284.             0, 0, SRCCOPY);
  285.  
  286.         dcMem.SelectObject (pOldBitmap);
  287.     }
  288.  
  289.     pBrush = new CBrush (crColors[lpdis->itemID - IDM_COLOR_BLACK]);
  290.     CRect rect = lpdis->rcItem;
  291.     rect.DeflateRect (6, 4);
  292.     rect.left += bm.bmWidth;
  293.     dc.FillRect (rect, pBrush);
  294.     delete pBrush;
  295.  
  296.     dc.Detach ();
  297. }
  298.  
  299. void CMainWindow::InvertLine (CDC* pDC, CPoint ptFrom, CPoint ptTo)
  300. {
  301.     int nOldMode = pDC->SetROP2 (R2_NOT);
  302.  
  303.     pDC->MoveTo (ptFrom);
  304.     pDC->LineTo (ptTo);
  305.  
  306.     pDC->SetROP2 (nOldMode);
  307. }
  308.  
  309. void CMainWindow::DeleteAllLines ()
  310. {
  311.     int nCount = m_lineArray.GetSize ();
  312.  
  313.     for (int i=0; i<nCount; i++)
  314.         delete m_lineArray[i];
  315.  
  316.     m_lineArray.RemoveAll ();
  317. }
  318.  
  319. BOOL CMainWindow::LoadFile (LPCSTR lpszFileName)
  320. {
  321.     CFile file;
  322.     BOOL bResult = TRUE;
  323.  
  324.     if (file.Open (lpszFileName, CFile::modeRead)) {
  325.         CWaitCursor wait;
  326.         DeleteAllLines ();
  327.         CArchive ar (&file, CArchive::load);
  328.         m_lineArray.Serialize (ar);
  329.         Invalidate ();
  330.     }
  331.     else {
  332.         CString string;
  333.         string.Format ("Unable to open %s", lpszFileName);
  334.         MessageBox (string, "Error", MB_ICONEXCLAMATION | MB_OK);
  335.         bResult = FALSE;
  336.     }
  337.     return bResult;
  338. }
  339.  
  340. BOOL CMainWindow::SaveFile (LPCSTR lpszFileName)
  341. {
  342.     CFile file;
  343.     BOOL bResult = TRUE;
  344.  
  345.     if (file.Open (lpszFileName, CFile::modeCreate | CFile::modeWrite)) {
  346.         CWaitCursor wait;
  347.         CArchive ar (&file, CArchive::store);
  348.         m_lineArray.Serialize (ar);
  349.     }
  350.     else {
  351.         CString string;
  352.         string.Format ("Unable to create %s", lpszFileName);
  353.         MessageBox (string, "Error", MB_ICONEXCLAMATION | MB_OK);
  354.         bResult = FALSE;
  355.     }
  356.     return bResult;
  357. }
  358.  
  359. void CMainWindow::UpdateWindowTitle ()
  360. {
  361.     CString strTitle;
  362.  
  363.     if (m_strFileName.IsEmpty ())
  364.         strTitle = "Paint3";
  365.     else
  366.         strTitle = m_strFileName + " - Paint3";
  367.  
  368.     SetWindowText (strTitle);
  369. }
  370.  
  371. /////////////////////////////////////////////////////////////////////////
  372. // CLine member functions
  373.  
  374. IMPLEMENT_SERIAL (CLine, CObject, 1)
  375.  
  376. CLine::CLine (CPoint ptFrom, CPoint ptTo, UINT nWidth, COLORREF crColor)
  377. {
  378.     m_ptFrom = ptFrom;
  379.     m_ptTo = ptTo;
  380.     m_nWidth = nWidth;
  381.     m_crColor = crColor;
  382. }
  383.  
  384. void CLine::Serialize (CArchive& ar)
  385. {
  386.     CObject::Serialize (ar);
  387.  
  388.     if (ar.IsStoring ())
  389.         ar << m_ptFrom << m_ptTo << m_nWidth << (DWORD) m_crColor;
  390.     else
  391.         ar >> m_ptFrom >> m_ptTo >> m_nWidth >> (DWORD) m_crColor;
  392. }
  393.  
  394. void CLine::Draw (CDC* pDC)
  395. {
  396.     CPen pen (PS_SOLID, m_nWidth, m_crColor);
  397.  
  398.     CPen* pOldPen = pDC->SelectObject (&pen);
  399.     pDC->MoveTo (m_ptFrom);
  400.     pDC->LineTo (m_ptTo);
  401.  
  402.     pDC->SelectObject (pOldPen);
  403. }
  404.